package com.qire.manhua.view.animator;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.os.Build;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

import com.qire.common.basic.ObjectUtil;
import com.qire.common.widget.animation.AnimationBinder;
import com.qire.common.widget.animation.AnimationUtils;

import androidx.core.view.ViewCompat;

public class TopFoldingAnimationBinder extends AnimatorListenerAdapter implements AnimationBinder, AnimatorUpdateListener {

    /**
     * 使用View移动函数的API版本
     */
    private static final boolean USE_OFFSET_API = Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT <= 19;

    /**
     * 默认动画时长
     */
    private static final int ANIMATION_DURATION = 500;

    /**
     * 隐退时间
     */
    static final int ANIMATION_FADE_DURATION = 180;

    /**
     * 退出回收的动画对象
     */
    private final ValueAnimator animator = new ValueAnimator();

    /**
     * 操作的View
     */
    private View view;

    /**
     * 上一次动画计算的值
     */
    private int previousAnimatedIntValue = 0;

    /**
     * 需要移动的Y轴距离，取决于View的高度。
     */
    private int translationY = 0;

    /**
     * 是进场动画么？true 是 false 不是
     */
    private boolean isIn = false;

    private final OnAttachStateChangeListener detachedFromWindowListener = new OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View v) { }
        @Override
        public void onViewDetachedFromWindow(View v) { destroy(); }
    };

    private final ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = this::getTranslationY;

    public TopFoldingAnimationBinder() {
        animator.setDuration(ANIMATION_DURATION);
        animator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
        animator.addUpdateListener(this);
        animator.addListener(this);
    }

    private void getTranslationY() {
        if(this.view == null) {
            this.translationY = 0;
        }
        this.translationY = this.view.getHeight();
        if(this.translationY > 0) {
            this.view.getViewTreeObserver().removeOnGlobalLayoutListener(globalLayoutListener);
        }
        ViewGroup.LayoutParams layoutParams = this.view.getLayoutParams();
        if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
            this.translationY += ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
        }
    }

    @Override
    public void bindView(View view) {
        isIn = false;
        if(ObjectUtil.nonNull(view)) {
            this.view = view;
            this.isIn = view.getVisibility() == View.VISIBLE;
            this.view.addOnAttachStateChangeListener(detachedFromWindowListener);
            this.view.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
        }
    }

    @Override
    public void destroy() {
        isIn = false;
        animator.cancel();
        if(ObjectUtil.nonNull(view)) {
            view.removeOnAttachStateChangeListener(detachedFromWindowListener);
            view = null;
        }
    }

    @Override
    public void onAnimationStart(Animator animator) {
        this.view.setVisibility(View.VISIBLE);
        long delay = 70;
        if(isIn) {
            this.view.setAlpha(0.0F);
            this.view.animate().alpha(1.0F).setDuration(ANIMATION_FADE_DURATION).setStartDelay(delay).start();
        } else {
            this.view.setAlpha(1.0F);
            this.view.animate().alpha(0.0F).setDuration(ANIMATION_FADE_DURATION).setStartDelay(delay).start();
        }
    }

    @Override
    public void onAnimationEnd(Animator animator) {
        if(isIn) {
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int currentAnimatedIntValue = (Integer) animator.getAnimatedValue();
        if (USE_OFFSET_API) {
            ViewCompat.offsetTopAndBottom(view, currentAnimatedIntValue - this.previousAnimatedIntValue);
        } else {
            view.setTranslationY((float) currentAnimatedIntValue);
        }
        this.previousAnimatedIntValue = currentAnimatedIntValue;
    }

    /**
     * 切换状态
     * @return 返回切换后的状态
     */
    public boolean toggle() {
        if(isIn) {
            playOut();
        } else {
            playIn();
        }
        return isIn;
    }

    public void playIn() {
        if(isIn == true) {
            return;
        }
        isIn = true;
        previousAnimatedIntValue = 0;

        if (USE_OFFSET_API) {
            ViewCompat.offsetTopAndBottom(view, -translationY);
        } else {
            view.setTranslationY((float) (-translationY));
        }

        animator.setIntValues(new int[]{-translationY, 0});
        animator.start();
    }

    public void playOut() {
        if(isIn == false) {
            return;
        }
        isIn = false;
        previousAnimatedIntValue = -translationY;

        animator.setIntValues(new int[]{0, -translationY});
        animator.start();
    }

}
